#include <qua/encode/decoder.h>
#include <qua/encode.h>
#include <stdexcept>

namespace qua
{
    namespace
    {
        typedef std::map< int, char >::iterator match_it;

        inline char index_to_char( int index ) { return static_cast< char >( index | 0x80 ); }
        inline int char_to_index( char sign ) { return static_cast< int >( sign & 0x7F ); }
    }

    char cp_decoder::to_char( int code )
    {
        if( encode::is_ascii( code ) ) return static_cast< char >( code );
        if( m_match.empty() ) match();
        match_it it = m_match.find( code );
        if( it == m_match.end() )
            throw std::invalid_argument( "Code is not presented in specified code page!" );
        return it->second;
    }

    int cp_decoder::to_unicode( char sign )
    {
        if( encode::is_ascii( sign ) ) return static_cast< int >( sign );
        int code = m_codes[ char_to_index( sign ) ];
        if( !code )
            throw std::invalid_argument( "Code is not defined in specified code page!" );
        return code;
    }

    void cp_decoder::match()
    {
        for( int i = 0; i < 0x80; i++ )
            m_match[ m_codes[i] ] = index_to_char( i );
    }
}
